梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)
本教程将从 C++ 二维数组的概念、定义、引用、初始化到越界问题和实际应用,全面拆解 C++ 二维数组的核心用法,帮助你掌握这一基础且重要的编程工具。
C++ 中的二维数组可以理解为“数组的数组”,是一种存储多行多列数据的复合数据结构,本质上是连续的内存空间中按“行优先”顺序存储的一维数组的扩展。
二维数组常用于描述具有行列结构的数据,例如:
二维数组的内存布局(以 2 行 3 列数组为例):
// int arr[2][3] = {{1,2,3}, {4,5,6}};
内存地址: 0x00 0x04 0x08 0x0C 0x10 0x14
存储值: 1 2 3 4 5 6
对应位置:arr[0][0] arr[0][1] arr[0][2] arr[1][0] arr[1][1] arr[1][2]
💡 核心特点:
二维数组的定义需指定“数据类型 + 数组名 + [行数] + [列数]”,核心语法如下:
// 静态二维数组(行数和列数必须是常量)
数据类型 数组名[行数][列数];
// 示例:定义一个3行4列的整型二维数组
int arr[3][4];
// 动态二维数组(C++11及以上,行数/列数可变量)
// 方式1:指针数组(每行可独立分配)
数据类型** 数组名 = new 数据类型*[行数];
for (int i = 0; i < 行数; i++) {
数组名[i] = new 数据类型[列数];
}
// 方式2:一维数组模拟二维数组
数据类型* 数组名 = new 数据类型[行数 * 列数];
#include <iostream>
using namespace std;
int main() {
// 定义2行3列的整型数组
int score[2][3];
// 定义4行2列的浮点型数组
float price[4][2];
// 定义5行5列的字符型数组
char chessboard[5][5];
cout << "二维数组定义完成" << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int rows = 3, cols = 4;
// 动态分配二维数组(指针数组)
int** arr = new int*[rows];
for (int i = 0; i < rows; i++) {
arr[i] = new int[cols];
}
cout << "动态二维数组分配完成" << endl;
// 释放内存(先释放列,再释放行)
for (int i = 0; i < rows; i++) {
delete[] arr[i];
}
delete[] arr;
arr = nullptr;
return 0;
}
二维数组的引用需通过“行下标 + 列下标”定位元素,下标从 0 开始,核心语法:数组名[行下标][列下标]。
#include <iostream>
using namespace std;
int main() {
// 定义并初始化3行2列数组
int arr[3][2] = {{10,20}, {30,40}, {50,60}};
// 引用单个元素
cout << "第1行第1列元素:" << arr[0][0] << endl; // 输出10
cout << "第2行第2列元素:" << arr[1][1] << endl; // 输出40
cout << "第3行第1列元素:" << arr[2][0] << endl; // 输出50
// 修改元素值
arr[1][0] = 35;
cout << "修改后第2行第1列元素:" << arr[1][0] << endl; // 输出35
// 遍历整个二维数组(双重循环)
cout << "\n遍历二维数组:" << endl;
for (int i = 0; i < 3; i++) { // 行循环
for (int j = 0; j < 2; j++) { // 列循环
cout << arr[i][j] << " ";
}
cout << endl; // 每行结束换行
}
return 0;
}
#include <iostream>
using namespace std;
int main() {
int rows = 2, cols = 3;
// 动态分配二维数组
int** arr = new int*[rows];
for (int i = 0; i < rows; i++) {
arr[i] = new int[cols];
// 给每行赋值
for (int j = 0; j < cols; j++) {
arr[i][j] = i * cols + j + 1; // 赋值1,2,3,4,5,6
}
}
// 引用并打印动态数组
cout << "动态二维数组元素:" << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
// 释放内存
for (int i = 0; i < rows; i++) {
delete[] arr[i];
}
delete[] arr;
arr = nullptr;
return 0;
}
C++ 支持多种二维数组初始化方式,核心包括完全初始化、部分初始化、省略行数初始化等。
// 按行初始化,每行用{}包裹
int arr[2][3] = {{1,2,3}, {4,5,6}};
// 等价于(省略行分隔,按行优先顺序)
int arr[2][3] = {1,2,3,4,5,6};
#include <iostream>
using namespace std;
int main() {
// 仅初始化第一行和第二行第一个元素
int arr[3][3] = {{1,2}, {3}};
// 遍历查看所有元素
cout << "部分初始化后的数组:" << endl;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
// 输出:
// 1 2 0
// 3 0 0
// 0 0 0
return 0;
}
#include <iostream>
using namespace std;
int main() {
// 省略行数,编译器根据初始化内容推导为2行3列
int arr[][3] = {{1,2,3}, {4,5,6}};
// 计算行数(总字节数 / 每行字节数)
int rows = sizeof(arr) / sizeof(arr[0]);
int cols = sizeof(arr[0]) / sizeof(arr[0][0]);
cout << "数组行数:" << rows << ",列数:" << cols << endl; // 输出2行3列
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
int main() {
int rows = 2, cols = 2;
int** arr = new int*[rows];
for (int i = 0; i < rows; i++) {
arr[i] = new int[cols];
// 方式1:逐个赋值
arr[i][0] = i + 1;
arr[i][1] = (i + 1) * 10;
// 方式2:批量赋值(memset仅适用于字符/字节型,整型建议循环)
// memset(arr[i], 0, cols * sizeof(int)); // 初始化为0
}
// 打印结果
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << arr[i][j] << " ";
}
cout << endl;
}
// 输出:
// 1 10
// 2 20
// 释放内存
for (int i = 0; i < rows; i++) {
delete[] arr[i];
}
delete[] arr;
return 0;
}
二维数组的下标越界是 C++ 中常见的错误,指访问了“行数/列数范围外”的元素,例如:3行3列数组访问 arr[3][0] 或 arr[0][3]。
⚠️ 越界危害:
#include <iostream>
using namespace std;
int main() {
int arr[2][2] = {{1,2}, {3,4}};
// 错误1:行下标越界(最大行下标为1,此处访问2)
cout << arr[2][0] << endl;
// 错误2:列下标越界(最大列下标为1,此处访问2)
arr[0][2] = 5;
return 0;
}
#include <iostream>
using namespace std;
int main() {
const int ROWS = 3, COLS = 3;
int arr[ROWS][COLS] = {{1,2,3}, {4,5,6}, {7,8,9}};
// 正确做法:循环时严格限制下标范围
for (int i = 0; i < ROWS; i++) { // i < ROWS 而非 i <= ROWS
for (int j = 0; j < COLS; j++) { // j < COLS 而非 j <= COLS
cout << arr[i][j] << " ";
}
cout << endl;
}
// 动态数组同理:用变量记录行数/列数,循环时严格校验
int rows = 2, cols = 4;
int** dynArr = new int*[rows];
for (int i = 0; i < rows; i++) {
dynArr[i] = new int[cols];
for (int j = 0; j < cols; j++) {
dynArr[i][j] = i * cols + j;
}
}
// 释放内存
for (int i = 0; i < rows; i++) {
delete[] dynArr[i];
}
delete[] dynArr;
return 0;
}
#include <iostream>
using namespace std;
int main() {
// 矩阵加法示例:2行2列矩阵相加
int mat1[2][2] = {{1,2}, {3,4}};
int mat2[2][2] = {{5,6}, {7,8}};
int res[2][2];
// 矩阵加法
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
res[i][j] = mat1[i][j] + mat2[i][j];
}
}
// 输出结果
cout << "矩阵加法结果:" << endl;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
cout << res[i][j] << " ";
}
cout << endl;
}
// 输出:
// 6 8
// 10 12
return 0;
}
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
// 3个学生,4门科目成绩
float scores[3][4] = {{85.5, 90.0, 78.0, 92.5},
{76.0, 88.5, 91.0, 85.0},
{90.5, 87.0, 89.5, 93.0}};
// 计算每个学生的平均分
cout << "学生平均分:" << endl;
for (int i = 0; i < 3; i++) {
float sum = 0.0;
for (int j = 0; j < 4; j++) {
sum += scores[i][j];
}
float avg = sum / 4;
cout << "第" << i+1 << "个学生:" << fixed << setprecision(1) << avg << endl;
}
return 0;
}
#include <iostream>
using namespace std;
int main() {
// 5x5五子棋棋盘:0=空,1=黑棋,2=白棋
int chessboard[5][5] = {{0,0,0,0,0},
{0,1,0,0,0},
{0,0,2,0,0},
{0,0,0,1,0},
{0,0,0,0,2}};
// 打印棋盘
cout << "五子棋棋盘:" << endl;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
cout << chessboard[i][j] << " ";
}
cout << endl;
}
return 0;
}
行下标 < 总行数 且 列下标 < 总列数;本教程从 C++ 二维数组的概念、定义、使用到越界问题和实际应用,全面拆解 C++ 二维数组的核心用法。掌握二维数组的运用,是学习数据结构和算法的重要基础之一。